import java.util.Iterator;
import java.util.List;
import java.util.Stack;

/**
 * {@link Zcsh}
 *
 * @author <a href="mailto:zcsh0721@163.com">Carey.zhou</a>
 * @version ${project.version}
 * @date 2020/11/30
 */
public class Zcsh implements Iterator<Integer> {

    private Stack<List<NestedInteger>> stack = new Stack<>();
    private Stack<Integer> stackIndex = new Stack<>();

    public Zcsh(List<NestedInteger> nestedList) {
        stack.push(nestedList);
        stackIndex.push(0);
    }

    @Override
    public Integer next() {
        if (hasNext()) {
            List<NestedInteger> peek = stack.peek();
            Integer pop = stackIndex.pop();
            stackIndex.push(pop + 1);
            return peek.get(pop).getInteger();
        }
        return null;
    }

    @Override
    public boolean hasNext() {
        while (!stack.empty()) {
            List<NestedInteger> stackPeek = stack.peek();
            Integer index = stackIndex.peek();
            if (stackPeek.size() <= index) {
                stack.pop();
                stackIndex.pop();
                if (!stackIndex.isEmpty()) {
                    stackIndex.push(stackIndex.pop() + 1);
                }
                continue;
            }

            NestedInteger nestedInteger = stackPeek.get(index);
            if (nestedInteger.isInteger()) {
                return true;
            }

            List<NestedInteger> list = nestedInteger.getList();
            if (!list.isEmpty()) {
                stack.push(list);
                stackIndex.push(0);
            } else {
                stackIndex.push(stackIndex.pop() + 1);
            }
        }

        return false;
    }
}


interface NestedInteger {
    // @return true if this NestedInteger holds a single integer, rather than a nested list.
    public boolean isInteger();

    // @return the single integer that this NestedInteger holds, if it holds a single integer
    // Return null if this NestedInteger holds a nested list
    public Integer getInteger();

    // @return the nested list that this NestedInteger holds, if it holds a nested list
    // Return null if this NestedInteger holds a single integerpublic List<NestedInteger> getList();
    public List<NestedInteger> getList();
}